home *** CD-ROM | disk | FTP | other *** search
/ Aminet 6 / Aminet 6 - June 1995.iso / Aminet / dev / src / adoc_src.lha / adoc-0.17 / mactab.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-03-20  |  13.6 KB  |  664 lines

  1. /*                                                               -*- C -*-
  2.  *  MACTAB.C
  3.  *
  4.  *  (c)Copyright 1995 by Tobias Ferber,  All Rights Reserved
  5.  *
  6.  *  This file is free software; you can redistribute it and/or modify
  7.  *  it under the terms of the GNU General Public License as published
  8.  *  by the Free Software Foundation; either version 1 of the License,
  9.  *  or (at your option) any later version.
  10.  *
  11.  *  This file is distributed in the hope that it will be useful,
  12.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.  *  GNU General Public License for more details.
  15.  *
  16.  *  You should have received a copy of the GNU General Public License
  17.  *  along with this program; see the file COPYING.  If not, write to
  18.  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  19.  */
  20.  
  21. /* $VER: $Id: mactab.c,v 1.2 1995/03/20 18:07:47 tf Exp $ */
  22.  
  23. #include <ctype.h>
  24. #include <string.h>
  25. #include <stdlib.h>
  26. #include <stdarg.h>
  27.  
  28. #include "mactab.h"
  29.  
  30. /* #of macro entries added when expanding dynamically */
  31. #define MACRESIZE  10
  32.  
  33. /* bytesize of a macro table for `n' macros */
  34. #define MACTABSIZE(n)  (size_t)( 2*(n) * sizeof(char *) + 2 )
  35.  
  36. typedef struct macnode {
  37.   struct macnode *succ, *pred;
  38.   int handle;           /* a unique macnode handle */
  39.   int reserved, used;   /* #of macros allocated (reserved) and used in mactab */
  40.   char **mactab;        /* the mactro table for strexpand() */
  41. } macnode_t;
  42.  
  43.  
  44. /* globals += */
  45. static int new_handle= 1;
  46. static macnode_t *maclist= (macnode_t *)0;
  47.  
  48. static macnode_t *macnode_head(macnode_t *this) { return (this && this->pred) ? macnode_head(this->pred) : this; }
  49. static macnode_t *macnode_tail(macnode_t *this) { return (this && this->succ) ? macnode_tail(this->succ) : this; }
  50.  
  51.  
  52. /* expand the `macnode.mactab' table for `num_macros' macros */
  53. static int macnode_expand(macnode_t *this, int num_macros)
  54. {
  55.   int result= 0;
  56.  
  57.   if(this)
  58.   {
  59.     char **new= (char **)realloc( (void *)(this->mactab), MACTABSIZE(this->reserved + num_macros) );
  60.  
  61.     if(new)
  62.     {
  63.       this->mactab= new;
  64.       result= (this->reserved += num_macros);
  65.     }
  66.   }
  67.  
  68.   return result;
  69. }
  70.  
  71.  
  72. /* allocate a new `macnode_t' structure with a `mactab' holding `num_macros' macros */
  73. static macnode_t *macnode_new(int num_macros)
  74. {
  75.   macnode_t *new= (macnode_t *)malloc( sizeof(macnode_t) );
  76.  
  77.   if(new)
  78.   {
  79.     new->succ     =
  80.     new->pred     = (macnode_t *)0;
  81.  
  82.     new->reserved =
  83.     new->used     = 0;
  84.  
  85.     new->mactab   = (char **)0;
  86.  
  87.     /* allocate the macro table */
  88.     if( macnode_expand(new,num_macros) )
  89.     {
  90.       /* set the last mactro to NIL */
  91.       new->mactab[0] =
  92.       new->mactab[1] = (char *)0;
  93.  
  94.       /* give this macnode a handle */
  95.       new->handle= new_handle++;
  96.     }
  97.     else /* !new->mactab */
  98.     {
  99.       free(new);
  100.       new= (macnode_t *)0;
  101.     }
  102.   }
  103.  
  104.   return new;
  105. }
  106.  
  107.  
  108. /* remove `this' from the `maclist' -- return `this' */
  109. static macnode_t *macnode_remove(macnode_t *this)
  110. {
  111.   if(this)
  112.   {
  113.     if(this->pred)
  114.       this->pred->succ= this->succ;
  115.  
  116.     else
  117.       maclist= this->succ;
  118.  
  119.     if(this->succ)
  120.       this->succ->pred= this->pred;
  121.  
  122.     this->pred =
  123.     this->succ = (macnode_t *)0;
  124.   }
  125.  
  126.   return this;
  127. }
  128.  
  129.  
  130. /* add a macnode_t list `this' to the global `maclist' */
  131. static void macnode_add(macnode_t *this)
  132. {
  133.   if(this)
  134.   {
  135.     macnode_tail(this)->succ= maclist;
  136.     maclist= macnode_head(this);
  137.   }
  138. }
  139.  
  140.  
  141. /* remove `this' from the `maclist' and dispose it */
  142. static macnode_t *macnode_dispose(macnode_t *this)
  143. {
  144.   if(this)
  145.   {
  146.     macnode_remove(this);
  147.  
  148.     if(this->mactab)
  149.     {
  150.       int n;
  151.  
  152.       for(n=0; n < 2*this->used; n++)
  153.       {
  154.         if( (this->mactab)[n] )
  155.           free( (this->mactab)[n] );
  156.       }
  157.  
  158.       free(this->mactab);
  159.     }
  160.     free(this);
  161.   }
  162.   return (macnode_t *)0;
  163. }
  164.  
  165.  
  166. /* find the macnode_t in the `maclist' via handle */
  167. static macnode_t *macnode_find(int handle)
  168. {
  169.   macnode_t *this= maclist;
  170.  
  171.   while( this && (this->handle != handle) )
  172.     this= this->succ;
  173.  
  174.   return this;
  175. }
  176.  
  177.  
  178. /* get the pointer to a macro `lhs' in `this->mactab' or the pointer to a new entry */
  179. static char **macnode_getmac(macnode_t *this, char *lhs)
  180. {
  181.   char **tab= (char **)0;
  182.  
  183.   if(this && this->mactab && lhs && *lhs)
  184.   {
  185.     int n;
  186.  
  187.     for(n=0, tab= this->mactab; n < 2*this->used; n+=2, tab= &tab[2])
  188.     {
  189.       if( *tab && !strcmp(*tab,lhs) )
  190.         break;
  191.     }
  192.   }
  193.  
  194.   return tab;
  195. }
  196.  
  197.  
  198.  
  199. /* modify a macro `lhs' w/ value `rhs' in `this' macnode_t's `mactab'.
  200.    The `rhs' of an existing macro `lhs' is replaced with the given `rhs',
  201.    an `rhs' == (char *)0 can be used to remove `lhs' from `this->mactab'. */
  202.  
  203. static int macnode_setmac(macnode_t *this, char *lhs, char *rhs)
  204. {
  205.   int err= 0;
  206.  
  207.   if(this && lhs && *lhs)
  208.   {
  209.     char **ptr= macnode_getmac(this,lhs);
  210.  
  211.     if(ptr)
  212.     {
  213.       if(*ptr) /* we found the macro `lhs' at the position `ptr' */
  214.       {
  215.         /* free the old `rhs' value */
  216.         if(ptr[1])
  217.           free(ptr[1]);
  218.  
  219.         if(rhs) /* set the new `rhs' value */
  220.         {
  221.           ptr[1]= strdup(rhs);
  222.  
  223.           if(!ptr[1])
  224.             err= 3;
  225.         }
  226.  
  227.         else /* remove this macro */
  228.         {
  229.           if(ptr[0])
  230.             free(ptr[0]);
  231.  
  232.           while(ptr[2])
  233.           {
  234.             ptr[0]= ptr[2];
  235.             ptr[1]= ptr[3];
  236.  
  237.             ptr= &ptr[2];
  238.           }
  239.  
  240.           ptr[0]= ptr[1]= (char *)0;
  241.  
  242.           this->used--;
  243.         }
  244.       }
  245.  
  246.       else if(rhs) /* `lhs' is a new macro */
  247.       {
  248.         if(this->used + 1 > this->reserved)
  249.         {
  250.           /* resize the macro table (add MACRESIZE new macro entries) */
  251.           if( macnode_expand(this, MACRESIZE) == 0 )
  252.             err= 4;
  253.         }
  254.  
  255.         if(err == 0)
  256.         {
  257.           char *l= strdup(lhs);
  258.           char *r= strdup(rhs);
  259.  
  260.           if(l && r)
  261.           {
  262.             ptr= &(this->mactab)[2*this->used];
  263.  
  264.             ptr[0]= l;
  265.             ptr[1]= r;
  266.  
  267.             ptr[2]=
  268.             ptr[3]= (char *)0;
  269.  
  270.             this->used++;
  271.           }
  272.           else /* strdup() failed */
  273.           {
  274.             if(l) free(l);
  275.             if(r) free(r);
  276.  
  277.             err= 3;
  278.           }
  279.         }
  280.       }
  281.       /* otherwise this was a no-op (:< */
  282.     }
  283.     else err= 2;
  284.   }
  285.   else err= 1;
  286.  
  287.   return err;
  288. }
  289.  
  290. /*
  291. **  PUBLIC
  292. */
  293.  
  294.  
  295. /****** mactab/mactab ********************************************************
  296. *
  297. *   NAME
  298. *    mactab -- Get the macro table associated with a handle
  299. *
  300. *   SYNOPSIS
  301. *    table= mactab( handle );
  302. *
  303. *    char **mactab( int handle );
  304. *
  305. *   FUNCTION
  306. *    This function returns the macro table with the given handle `handle'.
  307. *
  308. *   INPUTS
  309. *    handle          - The handle of the macro table
  310. *
  311. *   RESULT
  312. *    table          - A macro table for strexpand()
  313. *
  314. *   EXAMPLE
  315. *
  316. *   NOTES
  317. *
  318. *   BUGS
  319. *
  320. *   SEE ALSO
  321. *    mactab_new(), mactab_add(), strexpand()
  322. *
  323. ******************************************************************************
  324. *
  325. *  get the macro table `mactab' of the macnode_t in `maclist' with handle `handle'
  326. */
  327.  
  328. char **mactab(int handle)
  329. {
  330.   macnode_t *this= macnode_find(handle);
  331.   return this ? this->mactab : (char **)0;
  332. }
  333.  
  334.  
  335. /****** mactab/mactab_new ****************************************************
  336. *
  337. *   NAME
  338. *    mactab_new -- Allocate a new macro table
  339. *
  340. *   SYNOPSIS
  341. *    handle= mactab_new( num_macros );
  342. *
  343. *    int mactab_new( int num_macros );
  344. *
  345. *   FUNCTION
  346. *    This function allocates a new macro table which offers enough room
  347. *    to hold `num_macros' macros plus one NULL entry.  The value of
  348. *    `num_macros' should be > 0, however if more macros are added, then
  349. *    the macro table will be expanded dynamically.
  350. *
  351. *   INPUTS
  352. *    num_macros    - The number of macros reserved for this macro table.
  353. *            (should be > 0)
  354. *
  355. *   RESULT
  356. *    handle          - The handle of the allocated macro table or
  357. *            0 in case of an error.
  358. *
  359. *   EXAMPLE
  360. *
  361. *   NOTES
  362. *
  363. *   BUGS
  364. *
  365. *   SEE ALSO
  366. *    mactab_dispose(), mactab(), mactab_add(), strexpand()
  367. *
  368. ******************************************************************************
  369. *
  370. *  allocate a new macnode_t and reserve `num_macros' macros in the mactab
  371. */
  372.  
  373. int mactab_new(int num_macros)
  374. {
  375.   macnode_t *this= macnode_new(num_macros);
  376.  
  377.   if(this)
  378.     macnode_add(this);
  379.  
  380.   return this ? this->handle : 0;
  381. }
  382.  
  383.  
  384. /****** mactab/mactab_dispose ************************************************
  385. *
  386. *   NAME
  387. *    mactab_dispose -- Free one (or all) macro tables
  388. *
  389. *   SYNOPSIS
  390. *    null_handle= mactab_dispose( handle );
  391. *
  392. *    int mactab_dispose( int handle );
  393. *
  394. *   FUNCTION
  395. *    This function removes the macro table associated with `handle'
  396. *    and returns all memory allocated for it to the system free pool.
  397. *    If a negative handle is passed to this function then *ALL*
  398. *    macro tables will be disposed.
  399. *
  400. *   INPUTS
  401. *    handle          - The handle of the macro table to delete or
  402. *            `-1' to delete all macro tables.
  403. *
  404. *   RESULT
  405. *    null_handle   - a handle which is never associated with a
  406. *            macro table.
  407. *
  408. *   EXAMPLE
  409. *
  410. *   NOTES
  411. *
  412. *   BUGS
  413. *
  414. *   SEE ALSO
  415. *    mactab_new(), mactab_remove()
  416. *
  417. ******************************************************************************
  418. *
  419. *  dispose the macnode_t with handle `handle' or all macnode_t's if handle < 0
  420. */
  421.  
  422. int mactab_dispose(int handle)
  423. {
  424.   if(handle > 0)
  425.   {
  426.     macnode_t *this= macnode_find(handle);
  427.  
  428.     if(this)
  429.       this= macnode_dispose(this);
  430.   }
  431.   else if(handle < 0)
  432.   {
  433.     while(maclist)
  434.     {
  435.       macnode_t *this= maclist;
  436.       maclist= maclist->succ;
  437.       macnode_dispose(this);
  438.     }
  439.   }
  440.  
  441.   return 0;
  442. }
  443.  
  444. /****** mactab/mactab_remove *************************************************
  445. *
  446. *   NAME
  447. *    mactab_remove -- Remove one or more macros from a macro table
  448. *
  449. *   SYNOPSIS
  450. *    error= mactab_remove( handle, macro1, macro2, ..., (char *)0 );
  451. *
  452. *    int mactab_remove( int handle, ... );
  453. *
  454. *   FUNCTION
  455. *    This function removes all given macros from the macro table associated
  456. *    with the handle `handle'.  The list of macro names must be terminated
  457. *    with a (char *)0.
  458. *
  459. *   INPUTS
  460. *    handle          - The handle of the macro table
  461. *    ...          - A list of macro names with a trailing (char *)0
  462. *
  463. *   RESULT
  464. *    error          - != 0 in case of an error,  0 otherwise
  465. *
  466. *   EXAMPLE
  467. *
  468. *   NOTES
  469. *
  470. *   BUGS
  471. *
  472. *   SEE ALSO
  473. *    mactab_get(), mactab_add(), mactab_dispose()
  474. *
  475. ******************************************************************************
  476. *
  477. *  delete the given macros from the `mactab' of the macnode with handle `handle'
  478. */
  479.  
  480. int mactab_remove(int handle, ...)
  481. {
  482.   int err= 0;
  483.  
  484.   macnode_t *this= macnode_find(handle);
  485.  
  486.   if(this)
  487.   {
  488.     char *lhs;
  489.  
  490.     va_list argp;
  491.     va_start(argp,handle);
  492.  
  493.     do {
  494.       lhs= va_arg(argp, char *);
  495.  
  496.       if(lhs && *lhs)
  497.       {
  498.         /* set the `rhs' of each macro `lhs' to NIL */
  499.         err= macnode_setmac(this, lhs, (char *)0);
  500.       }
  501.     } while(lhs && *lhs && !err);
  502.  
  503.     va_end(argp);
  504.   }
  505.   else err= 1;
  506.  
  507.   return err;
  508. }
  509.  
  510.  
  511. /****** mactab/mactab_add ****************************************************
  512. *
  513. *   NAME
  514. *    mactab_add -- Add one or more macros to a macro table
  515. *
  516. *   SYNOPSIS
  517. *    error= mactab_add( handle, macro1, value1, ..., (char *)0 );
  518. *
  519. *    int mactab_add( int handle, ... );
  520. *
  521. *   FUNCTION
  522. *    This function adds the given macros to the macro table associated with
  523. *    given handle `handle'.  A (char *)0 terminates the list of macro names
  524. *    and macro values.  A macro value (char *)0 can be used to remove this
  525. *    macro from the list of macros in this table and is equivalent to a
  526. *    mactab_remove() call for this macro name.
  527. *
  528. *   INPUTS
  529. *    handle          - The handle of the macro table
  530. *    ...          - A list of macro names and macro values with a
  531. *            trailing (char *)0
  532. *
  533. *   RESULT
  534. *    error          - != 0 in case of an error,  0 otherwise
  535. *
  536. *   EXAMPLE
  537. *
  538. *   NOTES
  539. *
  540. *   BUGS
  541. *
  542. *   SEE ALSO
  543. *    mactab_remove(), mactab_new(), mactab_get(), mactab(), strexpand()
  544. *
  545. ******************************************************************************
  546. *
  547. *  add some macros to the `mactab' of the macnode_t with handle `handle'
  548. */
  549.  
  550. int mactab_add(int handle, ...)
  551. {
  552.   int err= 0;
  553.  
  554.   macnode_t *this= macnode_find(handle);
  555.  
  556.   if(this)
  557.   {
  558.     char *lhs, *rhs;
  559.  
  560.     va_list argp;
  561.     va_start(argp,handle);
  562.  
  563.     do {
  564.       lhs= va_arg(argp, char *);
  565.  
  566.       if(lhs && *lhs)
  567.       {
  568.         rhs= va_arg(argp, char *);
  569.         err= macnode_setmac(this,lhs,rhs);
  570.       }
  571.     } while(lhs && *lhs && !err);
  572.  
  573.     va_end(argp);
  574.   }
  575.   else err= 1;
  576.  
  577.   return err;
  578. }
  579.  
  580.  
  581. /****** mactab/mactab_get ****************************************************
  582. *
  583. *   NAME
  584. *    mactab_get -- Get the value of a macro
  585. *
  586. *   SYNOPSIS
  587. *    value= mactab_get( handle, name );
  588. *
  589. *    char *mactab_get( int handle, char *name );
  590. *
  591. *   FUNCTION
  592. *    This function returns the value of the macro `name' out of the table
  593. *    associated with the given handle `handle'.
  594. *
  595. *   INPUTS
  596. *    handle          - The handle of the macro table
  597. *    name          - The name of the macro
  598. *
  599. *   RESULT
  600. *    value          - The value of the macro `name' or 
  601. *            (char *)0 if `name' was not found
  602. *
  603. *   EXAMPLE
  604. *
  605. *   NOTES
  606. *
  607. *   BUGS
  608. *
  609. *   SEE ALSO
  610. *    mactab_new(), mactab_add(), mactab()
  611. *
  612. ******************************************************************************
  613. *
  614. *  get the macro table `mactab' of the macnode_t in `maclist' with handle `handle'
  615. */
  616.  
  617. char *mactab_get(int handle, char *lhs)
  618. {
  619.   char *rhs= (char *)0;
  620.  
  621.   macnode_t *this= macnode_find(handle);
  622.  
  623.   if(this)
  624.   {
  625.     char **ptr= macnode_getmac(this,lhs);
  626.  
  627.     if(ptr && *ptr)
  628.       rhs= ptr[1];
  629.   }
  630.  
  631.   return rhs;
  632. }
  633.  
  634.  
  635. #ifdef DEBUG
  636. #include <stdio.h>
  637.  
  638. void mactab_debug(FILE *fp)
  639. {
  640.   macnode_t *this;
  641.  
  642.   for(this= maclist; this; this= this->succ)
  643.   {
  644.     char **tab= this->mactab;
  645.  
  646.     fprintf(fp,"handle %d:  (reserved: %d, used: %d)\n",this->handle, this->reserved, this->used);
  647.  
  648.     if(tab)
  649.     {
  650.       int n;
  651.  
  652.       for(n=0; n<this->used; n++)
  653.       {
  654.         fprintf(fp,"\t\"%s\"\t\"%s\"\n", tab[0] ? tab[0] : "(nil)", tab[1] ? tab[1] : "(nil)");
  655.         tab= &tab[2];
  656.       }
  657.     }
  658.  
  659.     fprintf(fp,"\n");
  660.   }
  661. }
  662.  
  663. #endif /* DEBUG */
  664.